#include "sourcemsg.h"

#include <QFile>
#include <QDebug>

CSourceMsg::CSourceMsg()
		: CNetMsg(MSG_TYPE_SOURCE),
		m_pFileData(0)
{
}

CSourceMsg::~CSourceMsg()
{
	if (m_pFileData)
	{
		m_pFileData->setAutoRemove(true);
		m_pFileData->close();
		delete m_pFileData;
	}
}


void CSourceMsg::addSourceFiles(const QDir &basePath, const QStringList &slFilesToAdd)
{
	Q_ASSERT_X(basePath.exists(), Q_FUNC_INFO, "Base path does not exist!");
        qDebug() << "Adding files:" << slFilesToAdd << "from directory" << basePath;

	m_dBaseDir = basePath;
	m_slFiles = m_slFiles.unite(slFilesToAdd.toSet());
	qDebug() << m_slFiles;
}

void CSourceMsg::clearAddedFiles()
{
	m_slFiles.clear();
}

void CSourceMsg::reconstituteFiles(const QDir &basePath)
{
	qDebug() << "Writing source to:" << basePath.absolutePath();

	// first - check that the directory exists. If it doesn't, try and make it:
	if (!basePath.exists() && !basePath.mkpath(basePath.absolutePath()))
	{
		// nothing we can do here:
		qDebug() << "Path does not exist!";
		Q_ASSERT_X(0, Q_FUNC_INFO, "Could not create path to extract files to!");
		return;
	}

	if (!m_pFileData || !m_pFileData->isOpen())
		return;

	m_pFileData->seek(0);
	QDataStream s(m_pFileData);

	quint32 nNumFiles;
	s >> nNumFiles;

	qDebug() << "Reconstituting" << nNumFiles << "files";
	for (quint32 i = 0; i < nNumFiles && !s.atEnd(); i++)
	{
		QString strName;
		QByteArray baData;

		s >> strName >> baData;

		if (strName == "")
		{
			qDebug() << "ERROR: got blank filename.";
			break;
		}

		QString absPath = basePath.absoluteFilePath(strName);
		QFileInfo fi(absPath);
		// make sure the target directory exists:
		basePath.mkpath(fi.absoluteDir().absolutePath());

		// then create the output file:
		QFile f(fi.absoluteFilePath());
		if (!f.open(QIODevice::WriteOnly))
		{
			Q_ASSERT_X(0, Q_FUNC_INFO, qPrintable(QString("Could not open file '%1' for writing!").arg(fi.absoluteFilePath())));
			continue;
		}
		f.write(baData);
		f.close();
		qDebug() << "Wrote file:" << fi.absoluteFilePath();
	}

}

void CSourceMsg::setConfigPayload(const QString &strConfig)
{
	m_strXMLConfig = strConfig;
}

QString CSourceMsg::getConfigPayload() const
{
	return m_strXMLConfig;
}

void CSourceMsg::serialiseToStream(QDataStream &s) const
{
	// serialise config first:
	s << m_strXMLConfig;

	quint32 nNumFiles =0;
	// now iterate over all the files and make sure we have read permissions:
	for (QSet<QString>::const_iterator it = m_slFiles.constBegin();
		it != m_slFiles.constEnd();
		it++)
	{
            qDebug() << "Base directory is now:" << m_dBaseDir << "File path is:" << *it;
		QString path = m_dBaseDir.absoluteFilePath(*it);
		QFileInfo f(path);
		if (f.exists() && f.isReadable())
			nNumFiles++;
		else
		{
			qDebug() << "File" << path << "Is not readable or does not exist! Skipping...";
		}
	}

	// now we can serialise the number of files:
	qDebug() << "Sending" << nNumFiles << "files";
	s << nNumFiles;

	// and then we loop through all the files (again):
	for (QSet<QString>::const_iterator it = m_slFiles.constBegin();
		it != m_slFiles.constEnd();
		it++)
	{
		// for each file, open the file, then serialise the filepath and then the file contents:
		// here goes the filepath:
		s << *it;

		QFile f(m_dBaseDir.absoluteFilePath(*it));
		if (f.open(QIODevice::ReadOnly | QIODevice::Text))
		{
			s << f.readAll();
			f.close();
		}
		else
		{
			// something bad happened - serialise an empty QByteArray instead:
			s << QByteArray();
		}
	}
}

void CSourceMsg::serialiseFromStream(QDataStream &s)
{
	s >> m_strXMLConfig;

	// read number of files first:
	quint32 nNumFiles;
	s >> nNumFiles;

	if (m_pFileData)
		delete m_pFileData;

	m_pFileData = new QTemporaryFile;
	m_pFileData->open();

	QDataStream w(m_pFileData);

	qDebug() << "Number of files;" << nNumFiles;
	w << nNumFiles;

	for (quint32 i = 0; i< nNumFiles; i++)
	{
		QString strFileName;
		QByteArray baFileData;
		s >> strFileName >> baFileData;
		w << strFileName << baFileData;

		qDebug() << "File:" << strFileName << "contains" << baFileData.size() << "Bytes of data";
	}
}

